<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Module Weak
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora088.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora090.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Module <TT>Weak</TT></H2>
<A NAME="sec-weak"></A>
<A NAME="@fonctions334"></A>
<A NAME="@concepts202"></A>
<A NAME="@concepts203"></A>
<A NAME="@concepts204"></A>
<A NAME="@fonctions335"></A>
<A NAME="@fonctions336"></A>
<A NAME="@fonctions337"></A>A weak pointer is a pointer to a region
which the garbage collector may reclaim at any moment.
It may be surprising to speak of a value that might disappear at any
moment. In fact, we must see these weak pointers as a reservoir of
values that may still be available. This turns out to be particularly
useful when memory resources are small compared to the elements to be
saved. The classic case is the management of a memory cache: a value
may be lost, but it remains directly accessible as long as it exists.<BR>
<BR>
In Objective CAML one cannot directly manipulate weak pointers, only arrays of
weak pointers. The <TT>Weak</TT> module defines the abstract type <I>'a Weak.t</I>,
corresponding to the type <I>'a option array</I>, a vector of weak
pointers of type <TT>'a</TT>. The concrete type <I>'a option</I> is
defined as follows:
<PRE>
type 'a option = None | Some of 'a;;
</PRE><A NAME="@fonctions338"></A><A NAME="@fonctions339"></A><A NAME="@fonctions340"></A><A NAME="@fonctions341"></A>The main functions of this module are defined in figure
<A HREF="book-ora089.html#fig-mod-weak">9.14</A>.
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1>
<TR><TD  ALIGN=left NOWRAP>function</TD>
<TD  ALIGN=left NOWRAP>type</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><TT>create</TT></TD>
<TD  ALIGN=left NOWRAP><I>int -&gt; 'a t</I></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><TT>set</TT></TD>
<TD  ALIGN=left NOWRAP><I>'a t -&gt; int -&gt; 'a option -&gt; unit</I></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><TT>get</TT></TD>
<TD  ALIGN=left NOWRAP><I>'a t -&gt; int -&gt; 'a option</I></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP><TT>check</TT></TD>
<TD  ALIGN=left NOWRAP><I>'a t -&gt; int -&gt; bool</I></TD>
</TR></TABLE>
</DIV>
<BR>
<DIV ALIGN=center>Figure 9.14: Main functions of the <TT>Weak</TT> module.</DIV><BR>

<A NAME="fig-mod-weak"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>The <TT>create</TT> function allocates an array of weak pointers, each
initialized to <TT>None</TT>. The <TT>set</TT> function puts a value of type 
<I>'a option</I> at a specified index. The <TT>get</TT> function
returns the value contained at index <I>n</I> in a table of weak pointers.
The returned value is then referenced, and no longer reclaimable as long
as this reference exists. To verify the effective existence of a value,
one uses either the <TT>check</TT> function or pattern matching on the
<I>'a option</I> type's patterns. The former solution does not depend
on the representation choice for weak pointers.<BR>
<BR>
Standard functions for sequential structures also exist: <TT>length</TT>, for the length, and <TT>fill</TT> and
<TT>blit</TT> for copies of parts of the array.<BR>
<BR>

<H4> Example: an Image Cache</H4>
In an image-processing application, it is not rare to work on several
images. When the user moves from one image to another, the first is saved to
a file, and the other is loaded from another file. In general, only
the names of the latest images processed are saved. In order to avoid
overly frequent disk access while at the same time not using too much
memory space, we use a memory cache which contains the last images
loaded. The contents of the cache may be freed if necessary. We
implement this with a table of weak pointers, leaving the decision of
when to free the images up to the garbage collector. To load an image
we first search the cache. If the image is there, it becomes the
current image. If not, its file is read.<BR>
<BR>
We define a table of images in the following manner:


<PRE><BR># <B>type</B><CODE> </CODE>table_of_images<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>size<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>mutable</B><CODE> </CODE>ind<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>mutable</B><CODE> </CODE>name<CODE> </CODE><CODE>:</CODE><CODE> </CODE>string;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>mutable</B><CODE> </CODE>current<CODE> </CODE><CODE>:</CODE><CODE> </CODE>Graphics.color<CODE> </CODE>array<CODE> </CODE>array;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>cache<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE>string<CODE> </CODE><CODE>*</CODE><CODE> </CODE>Graphics.color<CODE> </CODE>array<CODE> </CODE>array<TT>)</TT><CODE> </CODE>Weak.t<CODE> </CODE>}<CODE> </CODE>;;<BR>

</PRE>

The field <TT>size</TT> gives the size of the table; the field
<TT>ind</TT> gives the index of the current image; the field
<TT>name</TT>, the name of the current image; the field
<TT>current</TT>, the current image, and the field <TT>cache</TT>
contains the array of weak pointers to the images. It contains the last
images loaded and their names.<BR>
<BR>
The function <TT>init_table</TT> initializes the table with its first image.


<PRE><BR># <B>let</B><CODE> </CODE>open_image<CODE> </CODE>filename<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>ic<CODE> </CODE><CODE>=</CODE><CODE> </CODE>open_in<CODE> </CODE>filename<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><TT>(</TT>input_value<CODE> </CODE>ic<TT>)</TT><CODE> </CODE><CODE>:</CODE><CODE> </CODE>Graphics.color<CODE> </CODE>array<CODE> </CODE>array<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><TT>(</TT><CODE> </CODE>close_in<CODE> </CODE>ic<CODE> </CODE>;<CODE> </CODE>i<CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>val open_image : string -&gt; Graphics.color array array = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>init_table<CODE> </CODE>n<CODE> </CODE>filename<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>open_image<CODE> </CODE>filename<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>let</B><CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE>Weak.create<CODE> </CODE>n<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>Weak.set<CODE> </CODE>c<CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>Some<CODE> </CODE><TT>(</TT>filename<CODE>,</CODE>i<TT>)</TT><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>{<CODE> </CODE>size<CODE>=</CODE>n;<CODE> </CODE>ind<CODE>=</CODE><CODE>0</CODE>;<CODE> </CODE>name<CODE> </CODE><CODE>=</CODE><CODE> </CODE>filename;<CODE> </CODE>current<CODE> </CODE><CODE>=</CODE><CODE> </CODE>i;<CODE> </CODE>cache<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<CODE> </CODE>}<CODE> </CODE>;;<BR><CODE>val init_table : int -&gt; string -&gt; table_of_images = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The loading of a new image saves the current image in the table and
loads the new one. To do this, we must first try to find the image in
the cache.


<PRE><BR># <B>exception</B><CODE> </CODE>Found<CODE> </CODE><B>of</B><CODE> </CODE>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>Graphics.color<CODE> </CODE>array<CODE> </CODE>array<CODE> </CODE>;;<BR># <B>let</B><CODE> </CODE>search_table<CODE> </CODE>filename<CODE> </CODE>table<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE>=</CODE><CODE>0</CODE><CODE> </CODE><B>to</B><CODE> </CODE>table<CODE>.</CODE>size<CODE>-</CODE><CODE>1</CODE><CODE> </CODE><B>do</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>i<CODE>&lt;&gt;</CODE>table<CODE>.</CODE>ind<CODE> </CODE><B>then</B><CODE> </CODE><B>match</B><CODE> </CODE>Weak.get<CODE> </CODE>table<CODE>.</CODE>cache<CODE> </CODE>i<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>n<CODE>,</CODE>img<TT>)</TT><CODE> </CODE><B>when</B><CODE> </CODE>n<CODE>=</CODE>filename<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE><TT>(</TT>Found<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>img<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>None<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE>Found<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>img<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>Some<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>img<TT>)</TT><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>load_table<CODE> </CODE>filename<CODE> </CODE>table<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>table<CODE>.</CODE>name<CODE> </CODE><CODE>=</CODE><CODE> </CODE>filename<CODE> </CODE><B>then</B><CODE> </CODE>()<CODE> </CODE><CODE> </CODE><CODE>(* the image is the current image *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>search_table<CODE> </CODE>filename<CODE> </CODE>table<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>i<CODE>,</CODE>img<TT>)</TT><CODE> </CODE>-&gt;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* the image found becomes the current image *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>current<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>img<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>name<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>filename<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>ind<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>i<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>None<CODE> </CODE>-&gt;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* the image isn't in the cache, need to load it *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* find an empty spot in the cache *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><TT>(</TT><CODE>!</CODE>i<CODE>&lt;</CODE>table<CODE>.</CODE>size<CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>Weak.check<CODE> </CODE>table<CODE>.</CODE>cache<CODE> </CODE><CODE>!</CODE>i<TT>)</TT><CODE> </CODE><B>do</B><CODE> </CODE>incr<CODE> </CODE>i<CODE> </CODE><B>done</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* if none are free, take a full slot *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>if</B><CODE> </CODE><CODE>!</CODE>i<CODE>=</CODE>table<CODE>.</CODE>size<CODE> </CODE><B>then</B><CODE> </CODE>i<CODE>:=</CODE><TT>(</TT>table<CODE>.</CODE>ind<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><B>mod</B><CODE> </CODE>table<CODE>.</CODE>size<CODE> </CODE><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* load the image here and make it the current one *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>current<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>open_image<CODE> </CODE>filename<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>ind<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>!</CODE>i<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>table<CODE>.</CODE>name<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>filename<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Weak.set<CODE> </CODE>table<CODE>.</CODE>cache<CODE> </CODE>table<CODE>.</CODE>ind<CODE> </CODE><TT>(</TT>Some<CODE> </CODE><TT>(</TT>filename<CODE>,</CODE>table<CODE>.</CODE>current<TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR><CODE>val load_table : string -&gt; table_of_images -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

The <TT>load_table</TT> function tests to see if the image requested
is current. If not, it checks the cache to see if the image exists; if
that fails, the function loads the image from disk. In either of the latter
two cases, it makes the image become the current one.<BR>
<BR>
To test this program, we use the following cache-printing function:


<PRE><BR># <B>let</B><CODE> </CODE>print_table<CODE> </CODE>table<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>to</B><CODE> </CODE>table<CODE>.</CODE>size<CODE>-</CODE><CODE>1</CODE><CODE> </CODE><B>do</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Weak.get<CODE> </CODE>table<CODE>.</CODE>cache<CODE> </CODE><TT>(</TT><TT>(</TT>i<CODE>+</CODE>table<CODE>.</CODE>ind<TT>)</TT><CODE> </CODE><B>mod</B><CODE> </CODE>table<CODE>.</CODE>size<TT>)</TT><CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>None<CODE> </CODE>-&gt;<CODE> </CODE>print_string<CODE> </CODE><CODE>"[] "</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Some<CODE> </CODE><TT>(</TT>n<CODE>,_</CODE><TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>print_string<CODE> </CODE>n<CODE> </CODE>;<CODE> </CODE>print_string<CODE> </CODE><CODE>" "</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><CODE> </CODE>;;<BR><CODE>val print_table : table_of_images -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Then we test the following program:


<PRE><BR># <B>let</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>init_table<CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>"IMAGES/animfond.caa"</CODE><CODE> </CODE>;;<BR><CODE>val t : table_of_images =</CODE><BR><CODE>  {size=10; ind=0; name="IMAGES/animfond.caa";</CODE><BR><CODE>   current=</CODE><BR><CODE>    [|[|7372452; 7372452; 7372452; 7372452; 7372452; 7372452; 7372452;</CODE><BR><CODE>        7372452; 7372452; 7372452; 7372452; 7372452; 7505571; 7505571; ...|];</CODE><BR><CODE>      ...|];</CODE><BR><CODE>   cache=...}</CODE><BR># load_table<CODE> </CODE><CODE>"IMAGES/anim.caa"</CODE><CODE> </CODE>t<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># print_table<CODE> </CODE>t<CODE> </CODE>;;<BR><CODE>IMAGES/anim.caa [] [] [] [] [] [] [] [] [] - : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
This cache technique can be adapted to various applications.<BR>
<BR>
<BR>
<BR>

<BR>
<BR>
<HR>
<A HREF="book-ora088.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora090.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
